package com.lizhao.win007com.crawler.webapi.impl;

import com.lizhao.win007.com.crawler.service.ICrawlerService;
import com.lizhao.win007com.commons.pojo.info.model.MonitorEasyInfo;
import com.lizhao.win007com.commons.pojo.info.model.MonitorEasyRealTimeInfo;
import com.lizhao.win007com.commons.pojo.info.model.MonitorEasyRealTimeTotalInfo;
import com.lizhao.win007com.commons.utils.HttpUtils;
import com.lizhao.win007com.crawler.webapi.mapper.CrawlerMapper;
import com.lizhao.win007com.info.service.IInfoService;
import com.lizhao.win007com.match.service.IMatchService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


import java.io.IOException;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
@Slf4j
@DubboService
public class CrawlerServiceImpl implements ICrawlerService {
    @DubboReference
    private IInfoService dubboInfoService;

    private static int HEADLESS = 0;
    private static Map<String, String> tagInfo = new HashMap<>();

    {
        tagInfo.put("-++", "3");
        tagInfo.put("0++", "3");
        tagInfo.put("-00", "3");
        tagInfo.put("-0+", "3");
        tagInfo.put("-+0", "3");

        tagInfo.put("+-+", "1");
        tagInfo.put("+0+", "1");
        tagInfo.put("0-0", "1");
        tagInfo.put("++-", "0");
        tagInfo.put("++0", "0");

        tagInfo.put("00-", "0");
        tagInfo.put("+0-", "0");
        tagInfo.put("0+-", "0");
        tagInfo.put("--+", "31");
        tagInfo.put("00+", "31");

        tagInfo.put("0-+", "31");
        tagInfo.put("--0", "31");
        tagInfo.put("+--", "10");
        tagInfo.put("+00", "10");
        tagInfo.put("+-0", "10");

        tagInfo.put("0--", "10");
        tagInfo.put("-+-", "30");
        tagInfo.put("0+0", "30");
        tagInfo.put("-0-", "30");
        tagInfo.put("+++", "F");

        tagInfo.put("---", "F");
        tagInfo.put("000", "F");
    }

    @DubboReference
    private IMatchService dubboMatchServer;

    @Autowired
    private CrawlerMapper crawlerMapper;

    // 处理欧指数据
    private Map<String, BigDecimal> getOdds(String oddsContentStr){
        Map mapList = new HashMap<>();
        mapList.put("begin", 0);
        mapList.put("odds", 0);
        mapList.put("end", 0);
        mapList.put("wholebegin", 0);
        mapList.put("wholeodds", 0);
        mapList.put("wholeend", 0);

        // 统计实时赔型的总数
        Map<String, Integer> mapTotal = new HashMap<>();
        mapTotal.put("-++", 0);
        mapTotal.put("0++", 0);
        mapTotal.put("-00", 0);
        mapTotal.put("-0+", 0);
        mapTotal.put("-+0", 0);

        mapTotal.put("+-+", 0);
        mapTotal.put("+0+", 0);
        mapTotal.put("0-0", 0);
        mapTotal.put("++-", 0);
        mapTotal.put("++0", 0);

        mapTotal.put("00-", 0);
        mapTotal.put("+0-", 0);
        mapTotal.put("0+-", 0);
        mapTotal.put("--+", 0);
        mapTotal.put("00+", 0);

        mapTotal.put("0-+", 0);
        mapTotal.put("--0", 0);
        mapTotal.put("+--", 0);
        mapTotal.put("+00", 0);
        mapTotal.put("+-0", 0);

        mapTotal.put("0--", 0);
        mapTotal.put("-+-", 0);
        mapTotal.put("0+0", 0);
        mapTotal.put("-0-", 0);
        mapTotal.put("+++", 0);

        mapTotal.put("---", 0);
        mapTotal.put("000", 0);

        String[] tmpList = oddsContentStr.split("==");
        String[] oddList = new String[tmpList.length - 1];

        System.arraycopy(tmpList,1,oddList,0,oddList.length);
        BigDecimal o3 = new BigDecimal("0");
        BigDecimal o1 = new BigDecimal("0");
        BigDecimal o0 = new BigDecimal("0");

        BigDecimal o33 = new BigDecimal("0");
        BigDecimal o11 = new BigDecimal("0");
        BigDecimal o00 = new BigDecimal("0");

        for (int i=0;i<oddList.length;i++){
            String[] tmp = oddList[i].split("\\|");

            BigDecimal tmp3 = new BigDecimal(tmp[3]);
            BigDecimal tmp1 = new BigDecimal(tmp[4]);
            BigDecimal tmp0 = new BigDecimal(tmp[5]);

            BigDecimal tmp33 = new BigDecimal(tmp[10]);
            BigDecimal tmp11 = new BigDecimal(tmp[11]);
            BigDecimal tmp00 = new BigDecimal(tmp[12]);

            String ptype = "";
            String tag3 = "";
            String tag1 = "";
            String tag0 = "";

            // tag3
            if (tmp33.compareTo(tmp3) == 0){
                tag3 = "0";
            } else if (tmp33.compareTo(tmp3) < 0){
                tag3 = "-";
            } else{
                tag3 = "+";
            }

            // tag1
            if (tmp11.compareTo(tmp1) == 0){
                tag1 = "0";
            } else if (tmp11.compareTo(tmp1) < 0){
                tag1 = "-";
            } else{
                tag1 = "+";
            }

            // tag0
            if (tmp00.compareTo(tmp0) == 0){
                tag0 = "0";
            } else if (tmp00.compareTo(tmp0) < 0){
                tag0 = "-";
            } else{
                tag0 = "+";
            }

            // 累加平均值
            o3 = o3.add(tmp3);
            o1 = o1.add(tmp1);
            o0 = o0.add(tmp0);

            o33 = o33.add(tmp33);
            o11 = o11.add(tmp11);
            o00 = o00.add(tmp00);

            ptype = tag3 + tag1 + tag0;
            int t = mapTotal.get(ptype);
            t++;

            mapTotal.put(ptype, t);
        }

        // 统计实时赔型总数
        for (Map.Entry<String, Integer> entry : mapTotal.entrySet()){
            int pageid = Integer.valueOf(tmpList[0]);
            MonitorEasyRealTimeTotalInfo monitorEasyRealTimeTotalInfo = new MonitorEasyRealTimeTotalInfo();
            monitorEasyRealTimeTotalInfo.setPageid(pageid);
            monitorEasyRealTimeTotalInfo.setPtype(entry.getKey());
            monitorEasyRealTimeTotalInfo.setPname(tagInfo.get(entry.getKey()));
            monitorEasyRealTimeTotalInfo.setTotal(entry.getValue());

            // 没有则添加， 有则修改赔型数量
            if (crawlerMapper.findRealTimeTotal(monitorEasyRealTimeTotalInfo) == null){
                // 添加实时赔型总数
                System.out.println("添加统计数据:" + pageid + "==" +entry.getKey() + "==" + tagInfo.get(entry.getKey())
                + "==" + entry.getValue());
                crawlerMapper.addRealTimeTotalInfo(monitorEasyRealTimeTotalInfo);
            } else{
                crawlerMapper.updateRealTimeTotalInfo(monitorEasyRealTimeTotalInfo);
            }
        }


        //divisor: 被除数
        //scale: 保留小数点后的位数
        //roundingMode: 使用的保留位数的模式
        //BigDecimal.ROUND_DOWN:直接省略多余的小数，比如1.28如果保留1位小数，得到的就是1.2
        //BigDecimal.ROUND_UP:直接进位，比如1.21如果保留1位小数，得到的就是1.3
        //BigDecimal.ROUND_HALF_UP:四舍五入，2.35保留1位，变成2.4
        //BigDecimal.ROUND_HALF_DOWN:四舍五入，2.35保留1位，变成2.3

        BigDecimal total = new BigDecimal(oddList.length);
        System.out.println(total);


        mapList.put("begin", o3.divide(total, 2, BigDecimal.ROUND_HALF_DOWN));
        mapList.put("odds", o1.divide(total, 2, BigDecimal.ROUND_HALF_DOWN));
        mapList.put("end", o0.divide(total, 2, BigDecimal.ROUND_HALF_DOWN));

        mapList.put("wholebegin", o33.divide(total, 2, BigDecimal.ROUND_HALF_DOWN));
        mapList.put("wholeodds", o11.divide(total, 2, BigDecimal.ROUND_HALF_DOWN));
        mapList.put("wholeend", o00.divide(total, 2, BigDecimal.ROUND_HALF_DOWN));

        return mapList;
    }

    //修改实时数据
    private void updateRealTimeInfo(MonitorEasyRealTimeInfo monitorEasyRealTimeInfo){
        // 修改今日数据
        crawlerMapper.updateRealTimeInfo(monitorEasyRealTimeInfo);
    }

    // 获取实时今日数据
    @Override
    public List<MonitorEasyRealTimeInfo> getRealTimeData() throws IOException, InterruptedException {
        String url = "http://op1.titan007.com/index_big.aspx";

        // 谷歌浏览器
//        System.setProperty("webdriver.chrome.driver","D:\\Program Files\\Python311\\chromedriver.exe");
//        ChromeDriver chromeDriver = new ChromeDriver();
//        chromeDriver.get(url);

        /******************** 配置火狐浏览器 ************************/

        // 设置驱动
        System.setProperty("webdriver.geckodriver.driver","D:\\Program Files\\Python311\\geckodriver.exe");

        /***************** 采集赛事的浏览器配置 开始 **********************/
        // 设置无头模式（不打开浏览器）
        FirefoxOptions firefoxOptions = new FirefoxOptions();
        if (HEADLESS == 0){
            firefoxOptions.addArguments("--headless");
        }
        FirefoxDriver firefoxDriver = new FirefoxDriver(firefoxOptions);
        /***************** 采集赛事的浏览器配置 结束 **********************/

        // 获取内容
        firefoxDriver.get(url);

        /***************** 采集盘口的浏览器配置 开始 **********************/
//        ChromeOptions chromeOptions = new ChromeOptions();
//        chromeOptions.addArguments("--headless");
//        ChromeDriver chromeDriver = new ChromeDriver(chromeOptions);
        /***************** 采集盘口的浏览器配置 结束 **********************/


        // 获取html里table里的文本
        String xpath = "//*[@id=\"table_schedule\"]//tr";
        List<WebElement> elements = firefoxDriver.findElements(By.xpath(xpath));

        // 遍历节点
        if (elements.size() > 0){
            for (WebElement element : elements){
                String trId = element.getAttribute("id");
                String trName = element.getAttribute("name");
//                System.out.println("id:" + trId + " name:" + trName);
//                System.out.println(element.getAttribute("outerHTML"));


                if (!trId.equals("")){
                    String[] splitId = trId.split("_");
                    if (!splitId[0].equals("tr2")){
                        String[] splitName = trName.split(",");
                        if (splitName[1].equals("1")){
                            List<WebElement> tdList = element.findElements(By.tagName("td"));
                            MonitorEasyRealTimeInfo monitorEasyRealTimeInfo = new MonitorEasyRealTimeInfo();

                            int i = 1;
                            if (tdList.size() > 0){
                                for (WebElement elTd : tdList){
                                    // leaguetype
                                    if (i == 2){
                                        monitorEasyRealTimeInfo.setLeaguetype(elTd.getText());
                                    }

                                    //matchdatetime
                                    if (i == 3){
                                        String matchdatetime = elTd.getText().replace(" ", "");
                                        matchdatetime = matchdatetime.replaceAll("<br>", " ") + ":00";
                                        monitorEasyRealTimeInfo.setMatchdatetime(matchdatetime);
                                    }

                                    // hometeam、r1
                                    if (i == 4){
                                        String tmpHomeTeam = elTd.getText();
                                        String hometeam = tmpHomeTeam.replaceAll("\\[.*?\\]", "");
                                        monitorEasyRealTimeInfo.setHometeam(hometeam);

                                        Pattern pattern = Pattern.compile("\\[(.*?)\\]");
                                        Matcher matcher = pattern.matcher(tmpHomeTeam);

                                        if (matcher.find()){
                                            monitorEasyRealTimeInfo.setR1(matcher.group(1));
                                        }
                                    }

                                    // guestteam、r2
                                    if (i == 12){
                                        String tmpGuestTeam = elTd.getText();
                                        String guestteam = tmpGuestTeam.replaceAll("\\[.*?\\]", "");
                                        monitorEasyRealTimeInfo.setGuestteam(guestteam);

                                        Pattern pattern = Pattern.compile("\\[(.*?)\\]");
                                        Matcher matcher = pattern.matcher(tmpGuestTeam);

                                        if (matcher.find()){
                                            monitorEasyRealTimeInfo.setR2(matcher.group(1));
                                        }
                                    }

                                    // pageid
                                    if (i == 13){
                                        String matchUrl = elTd.findElement(By.tagName("a")).getAttribute("href");
                                        Pattern pattern = Pattern.compile("http://op1.titan007.com/Oddslist/(.*?)_2.htm");
                                        Matcher matcher = pattern.matcher(matchUrl);

                                        if (matcher.find()){
                                            monitorEasyRealTimeInfo.setPageid(Integer.valueOf(matcher.group(1)));
                                        }
                                    }

                                    i += 1;
                                }
                            }

                            // 无今日赛事数据，添加今日赛事数据
                            int pageid = monitorEasyRealTimeInfo.getPageid();
                            if (crawlerMapper.findRealTimeByPageId(pageid) == null){
                                // 添加今日赛事数据
                                System.out.println("添加赛事: " + pageid + "==" +
                                        monitorEasyRealTimeInfo.getHometeam() +
                                        "==" + monitorEasyRealTimeInfo.getGuestteam());
                                crawlerMapper.addRealTimeInfo(monitorEasyRealTimeInfo);
                            } else {
                                System.out.println("赛事: " + pageid + "==" +
                                        monitorEasyRealTimeInfo.getHometeam() +
                                        "==" + monitorEasyRealTimeInfo.getGuestteam() + " 已存在");
                            }
                        }
                    }
                }
            }
        }



        // 获取所有试试数据表的赛事
        List<MonitorEasyRealTimeInfo> list = crawlerMapper.findAllRealTimeInfo();
        for (MonitorEasyRealTimeInfo matchInfo : list){
            int pageid = matchInfo.getPageid();

            // 欧指数据地址
            String url3 = "http://1x2d.titan007.com/" + pageid + ".js";
            System.out.println(url3);

            // 主页标签
            String currentWindow = firefoxDriver.getWindowHandle();

            // 打开新标签
            firefoxDriver.executeScript("window.open('" + url3 + "','odds')");
            String windowName = "odds";
            Thread.sleep(2000);
            firefoxDriver.switchTo().window(windowName);

            String oddStr = firefoxDriver.getPageSource();
            oddStr = oddStr.replaceAll("\",\"", "==");
            oddStr = oddStr.replace("\"", "");

            Pattern pattern = Pattern.compile("game=Array\\((.*?)\\);");
            Matcher matcher = pattern.matcher(oddStr);

            String oddContent = pageid + "==";
            String tmpContent = "";

            if (matcher.find()){
                tmpContent = matcher.group(1);
            }

            oddContent = oddContent + tmpContent;
            Map mapOddList = getOdds(oddContent);

            MonitorEasyRealTimeInfo monitorEasyRealTimeInfo = new MonitorEasyRealTimeInfo();

            monitorEasyRealTimeInfo.setPageid(pageid);
            monitorEasyRealTimeInfo.setAvg3((BigDecimal) mapOddList.get("begin"));
            monitorEasyRealTimeInfo.setAvg1((BigDecimal) mapOddList.get("odds"));
            monitorEasyRealTimeInfo.setAvg0((BigDecimal) mapOddList.get("end"));

            monitorEasyRealTimeInfo.setRealtime3((BigDecimal) mapOddList.get("wholebegin"));
            monitorEasyRealTimeInfo.setRealtime1((BigDecimal) mapOddList.get("wholeodds"));
            monitorEasyRealTimeInfo.setRealtime0((BigDecimal) mapOddList.get("wholeend"));

            //修改实时数据
            updateRealTimeInfo(monitorEasyRealTimeInfo);

            // 关闭新标签
            Thread.sleep(1000);
            //firefoxDriver.executeScript("window.close()");

            // 跳转到第一个标签
            firefoxDriver.switchTo().window(currentWindow);
        }

        // 关闭火狐浏览器
        System.out.println("关闭并退出浏览器");
        firefoxDriver.quit();

        for (MonitorEasyRealTimeInfo matchInfo : list){
            int pageid = matchInfo.getPageid();
            int isbig51 = 0;
            int isbig90 = 0;

            // 通过pageid获取统计表赔型总数
            BigDecimal total = BigDecimal.valueOf(crawlerMapper.findRealTimeSumInfo(pageid));

            if (total.compareTo(BigDecimal.valueOf(0)) != 0){
                String avgtag = "";
                List<MonitorEasyRealTimeTotalInfo> infoList = crawlerMapper.findRealTimeTotalById(pageid);

                for (MonitorEasyRealTimeTotalInfo info : infoList){
                    BigDecimal div = new BigDecimal(String.valueOf(info.getTotal())).divide(total, 2, BigDecimal.ROUND_HALF_DOWN).multiply(BigDecimal.valueOf(100));
                    if (div.compareTo(BigDecimal.valueOf(0)) != 0){
                        avgtag += info.getPtype() + " / " + info.getPname() + " / " + div + "%<br>";
                    }

                    // 判断占比是否>=51%和<90%
                    if (div.compareTo(BigDecimal.valueOf(51)) != -1 && (div.compareTo(BigDecimal.valueOf(90))) == -1){
                        isbig51 = 1;
                    }

                    // 判断占比是否>=90和<=100%
                    if (div.compareTo(BigDecimal.valueOf(90)) != -1 && (div.compareTo(BigDecimal.valueOf(100))) != 1){
                        isbig90 = 1;
                    }
                }
                // 通过pageid获取平赔简易版数据
                String eh = "";
                String eg = "";
                String hh = "";
                String hg = "";

                MonitorEasyInfo monitorEasyInfo = dubboInfoService.getEasyInfoByPageId(pageid);
                if (monitorEasyInfo != null){
                    matchInfo.setEh(monitorEasyInfo.getEh());
                    matchInfo.setEg(monitorEasyInfo.getEg());
                    matchInfo.setHh(monitorEasyInfo.getHh());
                    matchInfo.setHg(monitorEasyInfo.getHg());
                } else {
                    matchInfo.setEh(eh);
                    matchInfo.setEg(eg);
                    matchInfo.setHh(hh);
                    matchInfo.setHg(hg);
                }
                matchInfo.setIsbig51(isbig51);
                matchInfo.setIsbig90(isbig90);
                matchInfo.setAvgtag(avgtag);

                crawlerMapper.updateRealInfo(matchInfo);
            }
        }

        // 获取所有试试数据表的赛事
        List<MonitorEasyRealTimeInfo> realTimeInfoList = crawlerMapper.findAllRealTimeInfo();
        return realTimeInfoList;
    }

    //更新亚盘、大小盘
    @Override
    public String updateAsianAndBigByUrlAndPageId(String url, Integer pageid) throws Exception {
        CloseableHttpClient httpClient = HttpClients.createDefault();

        String content = "";

        try {

            // 创建HttpGet对象，并将带参数的URI传递给构造函数
            HttpGet httpGet = new HttpGet(url);
            httpGet.setHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8");
            httpGet.setHeader("Accept-Language", "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2");
            httpGet.setHeader("Connection", "keep-alive");
            httpGet.setHeader("Content-Type", "text/html;charset=gb2312");
            httpGet.setHeader("Host", "vip.titan007.com");
            httpGet.setHeader("Referer", "https://live.titan007.com/indexall_big.aspx");
            httpGet.setHeader("Sec-Fetch-Dest", "document");
            httpGet.setHeader("Sec-Fetch-Mode", "navigate");
            httpGet.setHeader("Sec-Fetch-Site", "none");
            httpGet.setHeader("Upgrade-Insecure-Requests", "1");
            httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/113.0");

            // 发送GET请求，并获取响应对象
            CloseableHttpResponse response = httpClient.execute(httpGet);
            int code = response.getStatusLine().getStatusCode();

            if (code == 200){
                // 解析响应内容
                String responseBody = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
                if(responseBody.matches("暂无公司开盘")){
                    content = "暂无公司开盘";
                } else {
                    content = HttpUtils.checkAsianAndBigByPageId(pageid, responseBody);
                }
            } else if (code == 404) {
                System.out.println("采集不到数据！");
                content = pageid + "==";
            }

            // 关闭响应对象
            response.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                // 关闭HttpClient对象
                httpClient.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return content;
    }

    @Override
    public String getOddsByUrl(String url, Integer pageid) throws Exception {
        CloseableHttpClient httpClient = HttpClients.createDefault();

        String content = "";

        try {
            // 创建URIBuilder，用于构造带参数的URI
            URIBuilder uriBuilder = new URIBuilder(url);

            // 创建HttpGet对象，并将带参数的URI传递给构造函数
            HttpGet httpGet = new HttpGet(uriBuilder.build());httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/113.0");

            // 发送GET请求，并获取响应对象
            CloseableHttpResponse response = httpClient.execute(httpGet);
            int code = response.getStatusLine().getStatusCode();

            if (code == 200){
                // 解析响应内容
                String responseBody = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
                content = HttpUtils.checkOddsByPageId(pageid, responseBody);
            } else if (code == 404) {
                System.out.println("采集不到数据！");
                content = pageid + "==";
            }

            // 关闭响应对象
            response.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                // 关闭HttpClient对象
                httpClient.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return content;
    }
}